﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Util
{
    /// <summary>
    /// A simple implementation of the batch manager suitable for single threaded batch processing 
    /// </summary>
    public class SimpleBatchManager : IBatchManager
    {
        private String batchFile;
        private int skip;
        private int whichBatch;
        private int totalBatches;
        private int curItem;
        private List<String> items;


        /**
        /// Constructs a SimpleBatchManager object.
         *
        /// @param filename     the name of the batch file
        /// @param skip         number of records to skip between items
        /// @param whichBatch   which chunk of the batch should we process
        /// @param totalBatches the total number of chuncks that the batch is divided into.
         */
        public SimpleBatchManager(String filename,
                                  int skip, int whichBatch, int totalBatches) 
        {
            this.batchFile = filename;
            this.skip = skip;
            this.whichBatch = whichBatch;
            this.totalBatches = totalBatches;
        }


        /** Starts processing the batch */
        public void start()
        {
            curItem = 0;
            items = getBatchItems(batchFile);
        }


        /**
        /// Gets the next available batch item or null if no more are available
         *
        /// @return the next available batch item
        /// @throws IOException if an I/O error occurs while getting the next item from the batch file.
         */
        public BatchItem getNextItem()
        {
            if (curItem >= items.Count) 
            {
                return null;
            } else {
                String line = items[curItem++];
                return new BatchItem(BatchFile.getFilename(line),
                        BatchFile.getReference(line));
            }
        }


        /** Stops processing the batch */
        public void stop()
        {
        }


        /**
        /// Returns the name of the file
         *
        /// @return the filename
         */
        public String getFilename() 
        {
            return batchFile;
        }


        /**
        /// Gets the set of lines from the file
         *
        /// @param file the name of the file
         */
        private List<String> getBatchItems(String file)
        {
            List<String> list = BatchFile.getLines(file, skip);

            if (totalBatches > 1) 
            {
                int linesPerBatch = list.Count / totalBatches;
                if (linesPerBatch < 1) {
                    linesPerBatch = 1;
                }
                if (whichBatch >= totalBatches) {
                    whichBatch = totalBatches - 1;
                }
                int startLine = whichBatch* linesPerBatch;
                // last batch needs to get all remaining lines
                if (whichBatch == (totalBatches - 1)) 
                {
                    list = list.GetRange(startLine, list.Count);
                } 
                else 
                {
                    list = list.GetRange(startLine, startLine + linesPerBatch);
                }
            }
            return list;
        }

    }
}
